package lk.icta.core.service;

import lk.icta.common.entity.DSDivision;
import lk.icta.core.entity.Land;
import lk.icta.core.entity.LandApplication;
import lk.icta.core.entity.WorkflowTask;
import lk.icta.user.entity.User;

import java.util.Date;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;

/**
 * @author Tharanga Punchihewa
 * @author Supun Viraj Rathnayaka
 */
public interface LandApplicationManagementService {

    /**
     * Add a Land Application
     *
     * @param landApplication The Land Application to be added
     * @param user            The user requesting to add the Land Application
     */
    public void addLandInitialApplication(LandApplication landApplication, User user);

    public void addLandGrantInitialApplication(LandApplication landApplication, String permitNo, User user);

    /**
     * Add a Land Application
     *
     * @param landApplication The Land Application to be added
     * @param user            The user requesting to add the Land Application
     */
    public void addLandDetailApplication(LandApplication landApplication, long landRefNumber, long[] landList, User user);

    public void editLandDetailApplication(LandApplication landApplication, long landRefNumber, long[] landList, User user);

    public void attachLandToApplication(long landApplicationId, long landRefNumber, long[] landList, int alienationType, User user);

    public void acceptAndCompleteApplication(LandApplication landApplication, long landRefNumber, String comment, User user);

    public void acceptAndCompleteAndEditApplication(LandApplication landApplication, long landRefNumber, String comment, User user);

    public void rejectAndCompleteApplication(LandApplication landApplication, long landRefNumber, String comment, User user);

    public void notReceivedCompleteApplication(LandApplication landApplication, long landRefNumber, String comment, User user);

    public void approveAttachedLand(LandApplication landApplication, String comment, User user);

    public void rejectAttachedLand(LandApplication landApplication, String comment, User user);

    public void saveAttachedAlienationDoc(LandApplication landApplication, int isSign, User user);

    public void interviewLandDetailApplication(LandApplication landApplication, long landRefNumber, long[] landList, User user);

    // public void objectionHandled(LandApplication landApplication, long landRefNumber, long[] landList, User user);

    public void handleObjections(LandApplication landApplication, String comment, String objections, WorkflowTask workflowTask, User user);

    //  public void objectionApprove(LandApplication landApplication, long landRefNumber, long[] landList, User user);

    public void finalizeApplication(LandApplication landApplication, String comment, User user);

//    public void objectionHandlingCompleted(LandApplication landApplication, long landRefNumber, long[] landList, User user);

    public void interviewCompleteLandDetailApplication(LandApplication landApplication, long landRefNumber, long[] landList, User user);
    //public void associateLandToApplication(LandApplication landApplication, long landId, long[] landList, User user);

    /**
     * Update a Land Application
     *
     * @param landApplication The Land Application to be updated
     * @param user            The user requesting to update the Land Application
     */
    public void updateInitialLandApplication(LandApplication landApplication, User user);

//    public void attachLand(LandApplication landApplication, User user);

    /**
     * Attaching a land to the land application
     *
     * @param landApplication The Land Application to be updated
     * @param landId          Unique Key of the land record
     * @param user            The User who performs this action
     */
    // public void alienate(LandApplication landApplication, long landId, User user);

    /**
     * Complete land Application
     *
     * @param applicationId Id of the Land Application to be completed
     * @param user          The User who performs this action
     */
    public void completeLandApplication(long applicationId, User user);

    /**
     * get  a Land Application by application id
     *
     * @param id   The id of Land Application
     * @param user The user requesting to add the Land Application
     */
    public LandApplication getLandApplicationByIdUKey(long id, User user);

    /**
     * Filter Init Application From List
     *
     * @param user User requesting to Filter  the Land Application List
     * @return initial  land application list  to be approved
     */

    public List<LandApplication> getPendingApprovalInitLandApplicationList(User user);

    /**
     * Filter  Application From List
     *
     * @param user User requesting to Filter  the Land Application List
     * @return initial  land application list  to be approved
     */

    public List<LandApplication> getApplicationList(User user);

    /**
     * Search application of the DSDivision by person Name
     *
     * @param personName Person Name of the application to filter
     * @param user       User requesting to filter lands
     * @return List of applications match the filtering criteria.
     */
    public List<LandApplication> searchApplicationsOfDSDivisionByPersonName(String personName, User user);

    /**
     * Search application of the DSDivision by NIC
     *
     * @param nic  NIC of the application to filter
     * @param user User requesting to filter lands
     * @return List of applications match the filtering criteria.
     */
    public List<LandApplication> searchApplicationsOfDSDivisionByNIC(String nic, User user);


    /**
     * Filter Init Application From List for edit(rejected and data entry application)
     *
     * @param user User requesting to Filter  the Land Application List
     * @return initial  land application list  to be approved
     */

    public List<LandApplication> getPendingEditInitLandApplicationList(User user);

    /**
     * Filter Detail Application From List
     *
     * @param user User requesting to Filter  the Land Application List
     */

    public List<LandApplication> getPendingApprovalDetailLandApplicationList(User user);

    /**
     * Approve a Init Land Application
     *
     * @param applicationId The Land Application to be Approved
     * @param user          The user requesting to add the Land Application
     */
    public Map<String,String> approveInitLandApplication(long applicationId, String comment, User user);

    public void approveDetailedLandApplication(long id, String comment, User user);

    public void approveObjections(LandApplication landApplication, String comment, WorkflowTask workflowTask, User user);

    public void rejectDetailedLandApplication(long id, String comment, User user);

//    public void finalizeLandApplication(long id, User user);

//    public List<LandApplication> getFinalizedDetailLandApplicationList(User user);

    /**
     * Approve Land Application
     *
     * @param landApplication Land Application
     * @param user            The user who performs this action
     */
    public void approveLandApplication(LandApplication landApplication, String comment, User user);

    public void approveLandApplicationByLC(LandApplication landApplication, WorkflowTask task, String comment, User user);

    /**
     * Approve Land Application
     *
     * @param landApplication Land Application
     * @param user            The user who performs this action
     */
    public void approveSignDocApplication(LandApplication landApplication, String comment, User user);

    /**
     * Reject Land Application
     *
     * @param landApplication Land Application
     * @param user            The user who performs this action
     */
    public void rejectSignDocApplication(LandApplication landApplication, String comment, User user);

    /**
     * Reject Land Application
     *
     * @param id   Land Application id
     * @param user The user who performs this action
     */
    public void rejectLandApplication(long id, String comment, User user);

    /**
     * Approve a Init Land Application
     *
     * @param applicationId The Land Application to be Approved
     * @param user          The user requesting to add the Land Application
     */
    public void rejectInitLandApplication(long applicationId, String comment, User user);

    /**
     * Get approved application list to enter detail information
     *
     * @param user The user requesting  Land Application List
     */
    public List<LandApplication> getApprovedApplicationList(User user);


    public List<LandApplication> getApplicationListByStateAndAM(User user, LandApplication.State state,
                                                                int alienationMethod);

    public List<LandApplication> getShortListedCandidates(EnumSet<WorkflowTask> stateSet, int alienationMethod);

    /**
     * Find Application List to be marked as completed
     *
     * @param user User who perform this action
     * @return The list of land applications to be completed
     */
    public List<LandApplication> getApplicationsToBeCompleted(User user);

    /**
     * Find the list of applications by workflow state
     *
     * @param user  User who perform this action
     * @param state The state of the Land Application
     * @return The List of land applications corresponding to the state
     */
    public List<LandApplication> getApplicationsByState(User user, WorkflowTask state);

    /**
     * Find the list of applications by workflow state
     *
     * @param user  User who perform this action
     * @param state The state of the Land Application
     * @param districtId The seleced district
     * @return The List of land applications corresponding to the state
     */
    public List<LandApplication> getApplicationsByStateAndDistrict(User user, WorkflowTask state, int districtId);

    public List<LandApplication> getApplicationsByWorkFlowItemId(User user, int itemId);

    public List<LandApplication> getInitialApplicationsByState(User user, LandApplication.State state);

    public List<LandApplication> getApplicationsByStateSet(User user, EnumSet<WorkflowTask> stateSet);

    public List<LandApplication> getApplicationsByStateSetGn(User user, int gnId, EnumSet<WorkflowTask> stateSet);

    public void approveCompletedApplication(LandApplication landApplication, String comment, User user);

    public void rejectCompletedApplicationByDS(LandApplication landApplication, String comment, User user);

    public void approveLandAllocationWithByPass(LandApplication landApplication, String comment, User user);

    /**
     * Find the list of applications by workflow state
     *
     * @param user         User who perform this action
     * @param workflowTask The workflow state of the Alienation method of the Land Application
     * @return The List of land applications corresponding to the workflow state
     */
    public List<LandApplication> getApplicationsByWorkflowState(User user, WorkflowTask workflowTask);

    /**
     * Find the list of applications by workflow state
     *
     * @param user           User who perform this action
     * @param alienationType type of the alienation
     * @return The List of land initial  applications
     */
    public List<LandApplication> getLandApplicationListByAlienationType(int alienationType, User user);

    /**
     * Find the list of applications by workflow state
     *
     * @param user           User who perform this action
     * @param alienationType type of the alienation
     * @return The List of land initial  applications
     */
    public List<LandApplication> getSelectedLandApplicationListByAlienationType(int alienationType, User user);

    /**
     * Search application of the DSDivision by person Name
     *
     * @param dsDivisionId Id of the D.S.Division
     * @param user         User requesting to filter lands
     * @return List of applications match the filtering criteria.
     */
    public List<LandApplication> searchApplicationsByDsId(int dsDivisionId, User user);

    /**
     * Search application of the DSDivision by Ds List
     *
     * @param districtId Id of the D.S.Division
     * @param user       User requesting to filter lands
     * @return List of applications match the filtering criteria.
     */
    public List<LandApplication> searchApplicationsByDistrictId(int districtId, User user);

    /**
     * Update a Land Application Land Allocated Approved
     *
     * @param landApplication The Land Application to be updated
     * @param user            The user requesting to update the Land Application
     */
    public void updateDueDateLandApplication(LandApplication landApplication, User user);

    /**
     * Update a Land Application Land Allocated Approved
     *
     * @param landApplication The Land Application to be updated
     * @param user            The user requesting to update the Land Application
     */
    public void saveSetUpAction(LandApplication landApplication, User user);

    /**
     * Find the list of applications by  state and User
     *
     * @param user User who perform this action
     * @return The List of land applications corresponding to the state
     */
    public List<LandApplication> getApplicationsByStateSetAndUser(User user);

    public List<LandApplication> getApplicationsByUser(User user);

    public void saveLeasePaymentDetail(LandApplication landApplication, User user);

    /**
     * Get application of the DSDivision by person Name
     *
     * @param state        WorkFlowTask Status of the land application
     * @param dsDivisionId Id of the D.S.Division
     * @param user         User requesting to filter lands
     * @return List of applications match the filtering criteria.
     */
    public List<LandApplication> getApplicationsByStateAndDsId(WorkflowTask state, int dsDivisionId, User user);

    /**
     * Search application of the DSDivision by person Name
     *
     * @param holderName of the application to filter
     * @param user
     * @param state
     * @return List of applications match the filtering criteria.
     */
    public List<LandApplication> searchAlienationsByPersonName(String holderName, User user, WorkflowTask state);

    /**
     * Search applications by person NIC
     *
     * @param holderNIC of the application to filter
     * @param user      User requesting to filter lands
     * @param state
     * @return List of applications match the filtering criteria.
     */
    public List<LandApplication> searchAlienationsByNIC(String holderNIC, User user, WorkflowTask state);

    /**
     * Search applications by Alienation Serial Number
     *
     * @param alienationSerialNumber of the application to filter
     * @param user                   requesting to filter lands
     * @param state
     * @return List of applications match the filtering criteria.
     */
    public List<LandApplication> searchAlienationByAlienationSerialNumber(long alienationSerialNumber, User user, WorkflowTask state);

    /**
     * Search application by Land Serial Number
     *
     * @param landSerialNumber of the application to filter
     * @param user             requesting to filter lands
     * @param state
     * @return List of applications match the filtering criteria.
     */
    public List<LandApplication> searchAlienationByLandSerialNumber(long landSerialNumber, User user, WorkflowTask state);

    /**
     * Search application by Alienation Number
     *
     * @param alienationNumber Person Name of the application to filter
     * @param user             User requesting to filter lands
     * @param state
     * @return List of applications match the filtering criteria.
     */
    public List<LandApplication> searchAlienationByAlienationReferenceNumber(String alienationNumber, User user, WorkflowTask state);

    /**
     * Search application by Alienation Method
     *
     * @param alienationMethodId of the application to filter
     * @param user               requesting to filter lands
     * @param state
     * @return List of applications match the filtering criteria.
     */
    public List<LandApplication> searchAlienationByMethodId(int alienationMethodId, User user, WorkflowTask state);

    /**
     * Search application by Alienation Method
     *
     * @param user  requesting to filter lands
     * @param state
     * @return List of applications match the filtering criteria.
     */
    public List<LandApplication> searchAllAlienationByMethodId(User user, WorkflowTask state);

    /**
     * @param landApplication landApplication object
     * @return true if Objections are allowed to add
     */
    public boolean isObjectionsEnabled(LandApplication landApplication);

    public List<Object[]> getLandApplicationStats(int i, String searchBy, int initAppState, int wftState, Date fromDate, Date toDate, String language);

    public boolean backupLandApplication(LandApplication currentApplication, LandApplication.State backupState, User user);
}
